/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.commons.collections;

import com.android1.amarena2d.exceptions.ResourceExceededException;


public class FixedSizeBag<E> implements ReadOnlyCollectionAccess<E> {

    private static final int INITIAL_SIZE = 30;
    private E[] list;
    private int count;

    //cursor for iterator
    private int cur;

    public FixedSizeBag() {
        this(INITIAL_SIZE);
    }

    public FixedSizeBag(E[] list) {
        this.list = list;
        this.count = 0;

    }

    public FixedSizeBag(int initialSize) {
        list = (E[]) new Object[initialSize];
        count = 0;
    }


    public int getCapacity() {
        return list.length;
    }

    @Override
    public int getCount() {
        return 0;
    }

    public int size() {
        return count;
    }

    public boolean isEmpty() {
        return count == 0;
    }

    public boolean isFull() {
        return count == list.length;
    }

    public int add(E element) {
        if (count == list.length)
            throw new ResourceExceededException("capacity exceeded.");
        int index = findFreeIndex();
        add(index, element);
        return index;
    }

    public void add(int index, E e) {
        if (index < list.length && index >= 0) {
            list[index] = e;
            count++;
        }
    }

    public boolean remove(E element) {
        return remove(find(element));
    }

    public boolean remove(int index) {
        if (index < list.length && index >= 0) {
            if (list[index] != null) {
                list[index] = null;
                count--;
            } else
                return false;
        }
        return false;
    }

    public E get(int index) {
        if (index < list.length && index >= 0) {
            return list[index];
        }
        return null;
    }


    public void clear() {
        count = 0;
        for (int i = count; i < list.length; i++) {
            list[i] = null;
        }
    }

    public int find(E e) {
        for (int i = 0; i < count; i++) {
            if (list[i].equals(e))
                return i;
        }
        return -1;
    }

    private int findFreeIndex() {
        for (int i = 0; i < count; i++) {
            if (list[i] == null)
                return i;
        }
        return -1;
    }

    public boolean contains(E e) {
        for (int i = 0; i < count; i++) {
            if (list[i] != null && list[i].equals(e))
                return true;
        }
        return false;
    }

    public int findNext(int i) {
        if (i < 0 || i >= list.length)
            return -1;
        for (; i < count; i++) {
            if (list[i] != null)
                return i;
        }
        return -1;
    }


    @Override
    public void itr() {
        cur = findNext(0);
    }

    @Override
    public boolean hasNext() {
        return cur != -1 && findNext(cur) > -1;
    }

    @Override
    public E next() {
        if (cur == -1)
            return null;
        E found = list[cur];
        cur = findNext(cur);
        return found;
    }


}